package com.nuaa.shr.pls.utils;

import java.util.Collections;
import java.util.List;
import java.util.concurrent.Callable;

import org.uma.jmetal.solution.GridPermutationSolution;

public class AddToEPCallable implements Callable<Boolean> {

	private List<GridPermutationSolution<Integer>> solutionList;
	private GridPermutationSolution<Integer> solution;
	private double[] unitLen;	
	
	private double[] lb;
	
	public AddToEPCallable(List<GridPermutationSolution<Integer>> solutionList, 
			GridPermutationSolution<Integer> solution, double[] unitLen, double[] lb){
		this.solutionList = solutionList;
		this.solution = solution;
		this.unitLen = unitLen;
		this.lb = lb;
	}
	
	@Override
	public Boolean call() throws Exception {
//		System.out.println(Thread.currentThread().getName());
		GridComparator gridComara = new GridComparator();
		for (int i = solutionList.size() - 1; i >= 0; i--) {
			GridPermutationSolution<Integer> comparaSolution = solutionList.get(i);
			int compFlag = gridComara.compare(comparaSolution, solution);
			if (compFlag == -1) {
				return false;// 可跳出
			} else if (compFlag == 1) {
				solutionList.remove(i);// 需要持续进行
			} else {
				if (isEqualByGrid(comparaSolution, solution)) {
					if (replaceByDistance(solution, i, solutionList, 1.0)) {
						return true;
					} else
						return false;
				} // else 不在同一格子
			}
		}
		return true;
	}
	
	private boolean isEqualByGrid(GridPermutationSolution<Integer> solution,
			GridPermutationSolution<Integer> neighborSolution) {
		for(int i = 0;i<solution.getNumberOfObjectives();i++){
			if(solution.getGridCoordinate(i) != neighborSolution.getGridCoordinate(i))
				return false;
		}
		return true;
	}

	
	public boolean replaceByDistance(GridPermutationSolution<Integer> gridPermutationSolution, int i,
			List<GridPermutationSolution<Integer>> population, double norm) {
		GridPermutationSolution<Integer> solution = population.get(i);
		double solutionDistance  = 0.0;
		double neighborSolutionDistance = 0.0;
//		double sum = 0.0;
//		for(int k = 0;k<solution.getNumberOfObjectives();k++){
//			sum += solution.getObjective(k);
//		}
		for(int index = 0;index<solution.getNumberOfObjectives();index++){
			int coordinate = solution.getGridCoordinate(index);
			double coef = 1.0 / ((double) coordinate + 0.0000001);
//			double coef = 1.0;
			
			double gridIdealValue = lb[index] + coordinate * unitLen[index];
			solutionDistance += Math.pow((solution.getObjective(index)-gridIdealValue)*coef, norm);
			neighborSolutionDistance += Math.pow((gridPermutationSolution.getObjective(index)-gridIdealValue)*coef, norm);
		}
		solutionDistance = Math.pow(solutionDistance, 1.0/norm);
		neighborSolutionDistance = Math.pow(neighborSolutionDistance, 1.0/norm);
		if(neighborSolutionDistance < solutionDistance){
			population.remove(i);
			return true;
		}else return false;
		
	}
}
